package parser

import (
	"errors"
	"fmt"
	"project/schedule/model"
	"project/schedule/util"
)

func ParseDataDepartment(department string, general *model.General, departmentInfoMap *map[string]interface{}) {
	startDate := (*departmentInfoMap)["startDate"]
	general.Department[department] = &model.Department{ProposedStartDate: startDate.(string)}
}

func ParseDataStaff(department string, general *model.General, departmentInfoMap *map[string]interface{}) {
	stuff := (*departmentInfoMap)["stuff"]
	for employee, employeeInfo := range stuff.(map[string]interface{}) {
		staffObject := &model.Staff{}
		employeeInfoMap := employeeInfo.(map[string]interface{})
		groupLeaderMap := employeeInfoMap["groupLeader"].(map[string]interface{})
		staffObject.GroupLeader = make(map[string]bool)
		for scale, power := range groupLeaderMap {
			staffObject.GroupLeader[scale] = power.(bool)
		}
		judgeMap := employeeInfoMap["judge"].(map[string]interface{})
		staffObject.GroupJudge = make(map[string]bool)
		for scale, power := range judgeMap {
			staffObject.GroupJudge[scale] = power.(bool)
		}
		staffObject.GroupMember = make(map[string]bool)
		staffMap := employeeInfoMap["staff"].(map[string]interface{})
		for scale, power := range staffMap {
			staffObject.GroupMember[scale] = power.(bool)
		}
		vacationMap := employeeInfoMap["vacation"].([]interface{})
		for _, vacation := range vacationMap {
			keyValue := make(map[string]string)
			for key, value := range vacation.(map[string]interface{}) {
				keyValue[key] = value.(string)
			}
			if !util.MapValueNotEmpty(&keyValue) {
				continue
			}
			staffObject.Vacation = append(staffObject.Vacation, keyValue)
		}
		lendOut := employeeInfoMap["lendOut"].(bool)
		staffObject.LendOut = lendOut
		staffObject.Department = department
		general.Staff[employee] = staffObject
	}
}

func ParseDataProject(department string, general *model.General, departmentInfoMap *map[string]interface{}) error {
	project := (*departmentInfoMap)["project"]
	for projectName, projectInfo := range project.(map[string]interface{}) {
		projectObject := &model.Project{}
		projectInfoMap := projectInfo.(map[string]interface{})
		proposedDay := int(projectInfoMap["proposedDay"].(float64))
		proposedPeople := int(projectInfoMap["proposedPeople"].(float64))
		assignDate := projectInfoMap["assignDate"].(string)
		if assignDate != "" && util.WorkDayValue2Index[assignDate] == 0 {
			return errors.New(fmt.Sprintf("`%s`拟定日期%s不是工作日", projectName, assignDate))
		}
		local := projectInfoMap["local"].(bool)
		outPack := int(projectInfoMap["outPack"].(float64))
		lockMap := projectInfoMap["lock"].(map[string]interface{})
		lock := make(map[string]map[string]string)
		for employee, employeeInfo := range lockMap {
			employeeInfoMap := employeeInfo.(map[string]interface{})
			role := employeeInfoMap["role"].(string)
			startDate := employeeInfoMap["startDate"].(string)
			endDate := employeeInfoMap["endDate"].(string)
			if startDate == "" || endDate == "" {
				return errors.New("lock startDate or endDate empty")
			}
			lock[employee] = make(map[string]string)
			lock[employee]["role"] = role
			lock[employee]["startDate"] = startDate
			lock[employee]["endDate"] = endDate
		}
		projectObject.Name = projectName
		projectObject.OutPack = outPack
		projectObject.IsLocal = local
		projectObject.Department = department
		projectObject.ProposedDay = proposedDay
		projectObject.ProposedPerson = proposedPeople
		projectObject.ProposedStartDate = assignDate
		if len(lock) != 0 {
			err := CheckLockConflict(general, &lock, projectObject) // 如果固定日期与人员假期有冲突则抛出异常
			if err != nil {
				return err
			}
			UpdateLockAllocation(general, &lock, projectObject) // 将lock的项目直接加入排班结果
			UpdateLockRegion(general, &lock, projectObject)     // 更新人员workRegion
			UpdateLockAllocationWb(general, projectObject)      // 组员是否需要用外包补齐
			UpdateLockProposedStartDate(general, &lock, projectObject)
			continue
		}
		general.Project[projectName] = projectObject
	}
	return nil
}

func ParseData(general *model.General, body *map[string]interface{}) error {
	data, ok := (*body)["data"]
	if !ok {
		return errors.New("no data in body")
	}
	for department, departmentInfo := range data.(map[string]interface{}) {
		departmentInfoMap := departmentInfo.(map[string]interface{})
		ParseDataDepartment(department, general, &departmentInfoMap)
		ParseDataStaff(department, general, &departmentInfoMap)
		err := ParseDataProject(department, general, &departmentInfoMap)
		if err != nil {
			return err
		}
	}
	return nil
}
